package com.zhongfl.crm.service.impl.boss;

import com.zhongfl.crm.enums.boss.*;
import com.zhongfl.crm.exception.CRMException;
import com.zhongfl.crm.lixiao.mapper.*;
import com.zhongfl.crm.model.boss.*;
import com.zhongfl.crm.model.boss.BackStatus;
import com.zhongfl.crm.service.boss.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.heptagram.channel.api.common.AssertUtils;
import tech.heptagram.core.common.util.JsonUtil;
import tech.heptagram.staff.cas.common.ArgumentException;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.zhongfl.crm.enums.boss.WorkOrderStatus.UN_ASSIGNEE;


/**
 * 工单管理
 * Created by wangkun23 on 2018/5/03.
 */
@Service
public class WorkOrderServiceImpl implements WorkOrderService {
    final Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private WorkOrderMapper workOrderMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private AmibaStaffService amibaStaffService;

    @Resource
    private AmibaService amibaService;

    @Resource
    private SequenceService sequenceService;

    @Resource
    private OrderService orderService;

    @Resource
    private WorkOrderTypeService workOrderTypeService;

    @Resource
    private CommonLogService commonLogService;

    @Resource
    private OrderAssistUserMapper orderAssistUserMapper;

    @Resource
    private OrderTaskLogMapper orderTaskLogMapper;

    @Resource
    private UserWechatMapper userWechatMapper;

    @Resource
    private OrderMemorandumService orderMemorandumService;


    @Resource
    private MessageSendTaskService messageSendTaskService;

    @Resource
    private AttachmentService attachmentService;

    @Resource
    private WarrantService warrantService;


    /**
     * 判断工单是否存在
     *
     * @param orderNo
     * @param workOrderTypeCode
     * @return
     */
    public Boolean workOrderExist(String orderNo, WorkOrderTypeCode workOrderTypeCode) {
        List<WorkOrder> list = workOrderMapper.findByCodeAndStatus(orderNo, workOrderTypeCode, WorkOrderStatus.BACKED);
        return !list.isEmpty();
    }

    /**
     * 根据工单号查询
     *
     * @param workOrderNo
     * @return
     */
    @Override
    public WorkOrder findByWorkOrderNo(String workOrderNo) {
        WorkOrder workOrder = workOrderMapper.findByWorkOrderNo(workOrderNo);
        if (Objects.isNull(workOrder)) {
            return workOrder;
        }
        if (StringUtils.isNotEmpty(workOrder.getCreateStaffCode())) {
            AmibaStaff createStaff = amibaStaffService.findSingleByStaffCode(workOrder.getCreateStaffCode());
            workOrder.setCreateStaffMobile(Objects.nonNull(createStaff) ? createStaff.getStaffMobile() : StringUtils.EMPTY);
        }
        if (StringUtils.isNotEmpty(workOrder.getAssigneeStaffCode())) {
            AmibaStaff assigneeStaff = amibaStaffService.findSingleByStaffCode(workOrder.getAssigneeStaffCode());
            workOrder.setAssigneeStaffMobile(Objects.nonNull(assigneeStaff) ? assigneeStaff.getStaffMobile() : StringUtils.EMPTY);
        }
        if (StringUtils.isNotEmpty(workOrder.getClaimStaffCode())) {
            AmibaStaff claimStaff = amibaStaffService.findSingleByStaffCode(workOrder.getClaimStaffCode());
            workOrder.setClaimStaffMobile(Objects.nonNull(claimStaff) ? claimStaff.getStaffMobile() : StringUtils.EMPTY);
        }
        return workOrder;
    }

    /**
     * 根据订单号查询
     *
     * @param orderNo
     * @return
     */
    @Override
    public List<WorkOrder> findByOrderNo(String orderNo) {
        WorkOrderQuery workOrderQuery = new WorkOrderQuery();
        workOrderQuery.setOrderNo(orderNo);
        List<WorkOrder> list = workOrderMapper.findList(workOrderQuery);
        return list;
    }

    /**
     * 分配工单
     *
     * @param workOrderNo       工单编号
     * @param assigneeStaffCode 分配人员工编码
     * @param claimAmibaId      目标阿米巴ID
     * @param claimStaffCode    目标员工编码
     * @param remark            分配备注
     * @param createBy          操作人。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignee(String workOrderNo,
                         String assigneeStaffCode,
                         Integer claimAmibaId,
                         String claimStaffCode,
                         String remark,
                         String createBy) {
        AssertUtils.hasText(assigneeStaffCode, "分配人不能为空");
        AssertUtils.hasText(claimStaffCode, "执行人不能为空");
        AssertUtils.notNull(createBy, "操作人不能为空");
        AssertUtils.greaterThanZero(claimAmibaId, "执行阿米巴不能为空");

        WorkOrder workOrder = workOrderMapper.findByWorkOrderNo(workOrderNo);
        AssertUtils.notNull(workOrder, "工单不存在");

        // 接受阿米巴对象
        Amiba receiveAmiba = amibaService.findById(workOrder.getReceiveAmibaId());

        // 判断分配人是否可以分配此工单
         List<AmibaStaff> allReceiveAmibaStaffs = amibaStaffService.findByAmibaCode(receiveAmiba.getCode());
        List<String> allReceiveManagerCode = allReceiveAmibaStaffs.stream()
                .filter(s -> s.getRole() == AmibaStaffRole.MANAGER.getValue())
                .map(AmibaStaff::getStaffCode)
                .collect(Collectors.toList());
        if (!allReceiveManagerCode.contains(assigneeStaffCode)) {
            throw new CRMException("只有" + workOrder.getReceiveAmibaName() + "的巴长才能分配此工单");
        }

        // 判断完成分配人, 再来判断执行人, 包括执行的阿米巴和巴员
        List<Integer> allowReceiveAmibaIds = allReceiveAmibaStaffs.stream()
                .map(AmibaStaff::getAmibaId)
                .distinct()
                .collect(Collectors.toList());
        if (!allowReceiveAmibaIds.contains(claimAmibaId)) {
            throw new CRMException("不能分配给此巴处理此工单");
        }

        // 允许被分配的员工
        List<String> allowReceiveStaffCodes = allReceiveAmibaStaffs.stream()
                .filter(s -> s.getAmibaId().intValue() == claimAmibaId)
                .map(AmibaStaff::getStaffCode)
                .collect(Collectors.toList());
        if (!allowReceiveStaffCodes.contains(claimStaffCode)) {
            throw new CRMException("不能分配给此员工处理此工单");
        }

        Amiba claimAmiba = amibaService.findById(claimAmibaId);

        AmibaStaff assigneeStaff = allReceiveAmibaStaffs.stream()
                .filter(s -> s.getStaffCode().equals(assigneeStaffCode))
                .findFirst()
                .orElse(null);
        AmibaStaff claimStaff = allReceiveAmibaStaffs.stream()
                .filter(s -> s.getStaffCode().equals(claimStaffCode))
                .findFirst()
                .orElse(null);
        //修改工单的信息
        WorkOrder updateWorkOrder = new WorkOrder();
        updateWorkOrder.setWorkOrderNo(workOrderNo);

        updateWorkOrder.setAssigneeTime(new Date());
        updateWorkOrder.setAssigneeStaffCode(assigneeStaff.getStaffCode());
        updateWorkOrder.setAssigneeStaffName(assigneeStaff.getStaffName());
        updateWorkOrder.setClaimStaffCode(claimStaff.getStaffCode());
        updateWorkOrder.setClaimStaffName(claimStaff.getStaffName());
        updateWorkOrder.setReceiveAmibaId(claimAmiba.getId());
        updateWorkOrder.setReceiveAmibaName(claimAmiba.getName());
        updateWorkOrder.setStatus(WorkOrderStatus.ASSIGNED);
        updateWorkOrder.setRemark(remark);
        workOrderMapper.updateByWorkOrderNo(updateWorkOrder);


        //将工单的受理人添加为协作人
        Order temp = orderService.findByOrderNo(workOrder.getOrderNo());
        temp.setCurrentStaffCode(assigneeStaffCode);
        temp.setCurrentStaffName(createBy);
        //协作人的信息(受理人)
        AmibaStaff amibaStaff = new AmibaStaff();
        amibaStaff.setStaffCode(claimStaff.getStaffCode());
        amibaStaff.setStaffName(claimStaff.getStaffName());
        amibaStaff.setAmibaId(claimAmiba.getId());
        amibaStaff.setAmibaName(claimAmiba.getName());
        saveOrderAssistUser(temp, amibaStaff);

        //添加工单任务, 默认任务全部取消创建, 全部人工创建吧。
//        workOrderTaskService.createDefaultTask(workOrderNo, remark, createBy);

        try {
            StringBuilder sb = new StringBuilder();
            sb.append("工单状态由[").append(workOrder.getStatusName())
                    .append("] 变更为[ ").append(updateWorkOrder.getStatusName())
                    .append("] 分配人:").append(updateWorkOrder.getAssigneeStaffName())
                    .append(" 执行人:").append(updateWorkOrder.getClaimStaffName());
            commonLogService.add(
                    CommonLogType.WORK_ORDER,
                    CommonLogType.WORK_ORDER_STATUS_CHANGE,
                    updateWorkOrder.getWorkOrderNo(),
                    sb.toString(),
                    assigneeStaff.getStaffName());
        } catch (Exception e) {
            throw new CRMException("添加操作日志失败", e);
        }

        // 如果是资料采集工单,报卷工单或者放款工单,更新订单的交付经理为此工单执行人, 交付阿米巴为分配的真正阿米巴
        if (workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.INFORMATION) || workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.ROLLS) || workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.LOANED)) {
            orderService.updateDeliverManager(workOrder.getOrderNo(), claimAmibaId, claimStaff.getStaffCode(), claimStaff.getStaffName(), createBy);
        }
    }



    @Override
    @Transactional
    public void settled(String workOrderNo) {
        WorkOrder oldWorkOrder = findByWorkOrderNo(workOrderNo);
        if (oldWorkOrder.getStatus().equals(WorkOrderStatus.SETTLED)) {
            return;
        }
        AssertUtils.notNull(oldWorkOrder);

        WorkOrder updateWorkOrder = new WorkOrder();
        updateWorkOrder.setWorkOrderNo(workOrderNo);
        updateWorkOrder.setStatus(WorkOrderStatus.SETTLED);
        workOrderMapper.updateByWorkOrderNo(updateWorkOrder);

        // 添加工单完成操作日志
        try {
            commonLogService.add(
                    CommonLogType.WORK_ORDER,
                    CommonLogType.WORK_ORDER_STATUS_CHANGE,
                    updateWorkOrder.getWorkOrderNo(),
                    "工单结算完成, 状态由[" + oldWorkOrder.getStatusName() + "] 变更为[ " + updateWorkOrder.getStatusName() + "]",
                    "System");
        } catch (Exception e) {
            throw new CRMException("添加操作日志失败", e);
        }
    }

    /**
     * 取消工单
     *
     * @param workOrderNo
     * @return
     */
    @Override
    public void cancel(String workOrderNo, String currentName) {
        WorkOrder oldWorkOrder = findByWorkOrderNo(workOrderNo);
        if (oldWorkOrder.getStatus().equals(WorkOrderStatus.CANCEL)) {
            return;
        }
        AssertUtils.notNull(oldWorkOrder);

        WorkOrder updateWorkOrder = new WorkOrder();
        updateWorkOrder.setWorkOrderNo(workOrderNo);
        updateWorkOrder.setEndTime(new Date());
        updateWorkOrder.setStatus(WorkOrderStatus.CANCEL);
        // 添加工单取消日志
        try {
            commonLogService.add(
                    CommonLogType.WORK_ORDER,
                    CommonLogType.WORK_ORDER_STATUS_CHANGE,
                    updateWorkOrder.getWorkOrderNo(),
                    "工单结算完成, 状态由[" + oldWorkOrder.getStatusName() + "] 变更为[ " + updateWorkOrder.getStatusName() + "]",
                    currentName);
        } catch (Exception e) {
            throw new CRMException("添加操作日志失败", e);
        }
        workOrderMapper.updateByWorkOrderNo(updateWorkOrder);
    }

    /**
     * 更新工单
     *
     * @param workOrder
     */
    @Override
    public void update(WorkOrder workOrder) {
        AssertUtils.notNull(workOrder.getWorkOrderNo(), "工单号为空！");
        //TODO 更新工单的日志
        workOrderMapper.updateByWorkOrderNo(workOrder);
    }

    /**
     * 完成工单
     *
     * @param completedInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complete(RxWorkOrderCompleted completedInfo) {
        AssertUtils.notNull(completedInfo, "完成失败");
        AssertUtils.hasText(completedInfo.getWorkOrderNo(), "工单完成 工单号为空");
        AssertUtils.hasText(completedInfo.getOper(), "完成人不能为空");
        AssertUtils.hasText(completedInfo.getCompleteStaffCode(), "完成人不能为空");

        String workOrderNo = completedInfo.getWorkOrderNo();
        WorkOrder workOrder = workOrderMapper.findByWorkOrderNo(workOrderNo);

        if (workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.WARRANT)|| workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.MORTGAGES)){
            List<WarrantWorkOrderAttachment> warrantWorkOrderAttachments = warrantService.selectByWorkOrderNo(workOrderNo);
            if (CollectionUtils.isEmpty(warrantWorkOrderAttachments)) {
                throw new ArgumentException("凭证照片不能为空！！");
            }
        }

        // 判断完成人是否是受理巴的巴长或执行人
        String errorMessage = "只有" + workOrder.getReceiveAmibaName() + "的巴长或工单负责人才能发起结算";

        // 受理部门的员工列表
        List<AmibaStaff> receiveStaffs = amibaStaffService.findByAmibaId(workOrder.getReceiveAmibaId());

        AmibaStaff operStaff = receiveStaffs.stream()
                .filter(s -> s.getStaffCode().equals(completedInfo.getCompleteStaffCode()))
                .findFirst()
                .orElse(null);
        if (Objects.isNull(operStaff)) {
            throw new CRMException(errorMessage);
        }
        // 不是巴长, 也不是工单执行人, 不能发起结算
        if (operStaff.getRole() != AmibaStaffRole.MANAGER.getValue()
                && !operStaff.getStaffCode().equals(workOrder.getClaimStaffCode())) {
            throw new CRMException(errorMessage);
        }


        WorkOrder updateWorkOrder = new WorkOrder();
        updateWorkOrder.setWorkOrderNo(workOrderNo);
        updateWorkOrder.setEndTime(new Date());
        updateWorkOrder.setStatus(WorkOrderStatus.COMPLETED);
        workOrderMapper.updateByWorkOrderNo(updateWorkOrder);

        // 这个貌似没有用了, 如果有图片的话,可以用。
        if (!CollectionUtils.isEmpty(completedInfo.getFilePaths())) {
            for (String filePath : completedInfo.getFilePaths()) {
                attachmentService.save(filePath, workOrder.getOrderNo(), workOrder.getWorkOrderNo(), OrderAttachmentType.WORK_ORDER_COMPLETED.toString(), completedInfo.getOper());
            }
        }

        // 添加工单完成操作日志
        try {
            commonLogService.add(
                    CommonLogType.WORK_ORDER,
                    CommonLogType.WORK_ORDER_STATUS_CHANGE,
                    updateWorkOrder.getWorkOrderNo(),
                    "工单状态由[" + workOrder.getStatusName() + "] 变更为[ " + updateWorkOrder.getStatusName() + "]",
                    completedInfo.getOper());
        } catch (Exception e) {
            throw new CRMException("添加操作日志失败", e);
        }

        if (!completedInfo.getAutoGenerateNextWorkOrder()) {
            return;
        }

        //修改订单状态
        Order updateOrder = new Order();
        updateOrder.setOrderNo(workOrder.getOrderNo());
        //根据工单类型判断创建下一个工单
        WorkOrderTypeCode nextWorkOrderTypeCode = null;
        OrderStatus orderUpdateStatus = null;
        switch (workOrder.getWorkOrderTypeCode()) {
            case VALUATION:
            case COMPANY_WRAP:
            case INTERVIEW:
                logger.info("不修改任何状态：orderNo {}", workOrder.getOrderNo());
                break;
            case INFORMATION:
                //资料采集
                orderUpdateStatus = OrderStatus.STATUS_DECLARE;
                nextWorkOrderTypeCode = WorkOrderTypeCode.ROLLS;
                updateOrder.setInstoreTime(new Date());
                break;
            case ROLLS:
                //报卷
                orderUpdateStatus = OrderStatus.STATUS_APPROVAL;
                nextWorkOrderTypeCode = WorkOrderTypeCode.LOAN_APPROVE;
                updateOrder.setInstoreTime(new Date());
                break;
            case LOAN_APPROVE:
                //审批
                orderUpdateStatus = OrderStatus.STATUS_PIDAI;
                nextWorkOrderTypeCode = WorkOrderTypeCode.WARRANT;
                updateOrder.setInstoreTime(new Date());
                break;
            case WARRANT:
                //进抵
                orderUpdateStatus = OrderStatus.STATUS_STORAGE;
                nextWorkOrderTypeCode = WorkOrderTypeCode.MORTGAGES;
                updateOrder.setInstoreTime(new Date());
                break;
            case MORTGAGES:
                //他证
                orderUpdateStatus = OrderStatus.STATUS_APPLICAT;
                nextWorkOrderTypeCode = WorkOrderTypeCode.LOANED;
                updateOrder.setInstoreTime(new Date());
                break;
            case LOANED:
                //放款
                orderUpdateStatus = OrderStatus.STATUS_ACCOUNT;
                nextWorkOrderTypeCode = WorkOrderTypeCode.LIQUIDATION;
                updateOrder.setInstoreTime(new Date());
                break;
            case LOAN_FEE:
                //收服务费
                //生成订单清算工单，完成后才可以关闭订单
                nextWorkOrderTypeCode = WorkOrderTypeCode.LIQUIDATION;
                updateOrder.setInstoreTime(new Date());
                break;
            //case LIQUIDATION:
            //    //订单清算
            //    orderUpdateStatus = OrderStatus.STATUS_COMPLETED;
            //    break;
            default:
                break;
        }
        // 工单完成更改订单状态
        if (orderUpdateStatus != null) {
            updateOrder.setStatus(orderUpdateStatus);
            updateOrder.setCreatedBy(completedInfo.getOper());
            updateOrder.setOperStaffCode(completedInfo.getCompleteStaffCode());
            orderService.updateStatus(updateOrder);
        }
        // 如果有下一步工单, 则自动创建之
        if (nextWorkOrderTypeCode != null) {
            //创建下一个工单 暂时创建人用指派的员工
            ServiceResult<String> serviceResult = this.create(workOrder.getOrderNo(),
                    // 工单发起人, 创建方法里会更改的, 所以直接使用当前完成的工单发起人
                    workOrder.getCreateStaffCode(),
                    nextWorkOrderTypeCode,
                    "无",
                    completedInfo.getOper(),
                    null);
            // 创建完成工单后, 有些工单需要进行自动分配。
            if (serviceResult.isSuccess()) {
                String nextWorkOrderNo = serviceResult.getResult();

                // 如果是报卷工单, 自动进行分配。分配人应该是交付巴巴长,即资料采集工单分配人, 执行人是交付经理
                //报卷和他证都是上一个订单的分配人执行人
                if (nextWorkOrderTypeCode.equals(WorkOrderTypeCode.ROLLS) || nextWorkOrderTypeCode.equals(WorkOrderTypeCode.LOAN_APPROVE) || nextWorkOrderTypeCode.equals(WorkOrderTypeCode.MORTGAGES)) {
                    AmibaStaff assignessStaff = getAssignessStaff(workOrder, receiveStaffs);
                    //判断要分配的员工是否还是当初采集工单时的那个交付巴的成员，如果没变则自动分配，变了则不自动分配
                    //要分配的交付经理所在的阿米巴
                    Optional<AmibaStaff> claimStaffOptional = receiveStaffs.stream()
                            .filter(s -> s.getStaffCode().equals(workOrder.getClaimStaffCode()))
                            .findAny();
                    if (claimStaffOptional.isPresent()) {
                        this.assignee(nextWorkOrderNo,
                                assignessStaff.getStaffCode(),
                                workOrder.getReceiveAmibaId(),
                                workOrder.getClaimStaffCode(),
                                "自动分配",
                                "System"
                        );
                    }
                }
                // 如果下一步是放款工单, 则当前工单为进抵工单, 工单的分配人和处理人都是风进抵的人,
                // 不能用当前工单信息
                // 商务->交付
                if (nextWorkOrderTypeCode.equals(WorkOrderTypeCode.LOANED)) {
                    // 找到当时做的资料采集工单
                    WorkOrder informationWorkOrder = workOrderMapper.selectByOrderNoAndType(workOrder.getOrderNo(), WorkOrderTypeCode.INFORMATION);
                    // 受理部门的员工列表
                    List<AmibaStaff> informationReceiveStaffs = amibaStaffService.findByAmibaId(informationWorkOrder.getReceiveAmibaId());
                    AmibaStaff assignessStaff = getAssignessStaff(informationWorkOrder, informationReceiveStaffs);

                    //判断要分配的员工是否还是当初采集工单时的那个交付巴的成员，如果没变则自动分配，变了则不自动分配
                    //要分配的交付经理所在的阿米巴
                    List<AmibaStaff> list = amibaStaffService.findByStaffCode(informationWorkOrder.getClaimStaffCode());
                    for (AmibaStaff amibaStaff : list) {
                        //当初交付经理所在的阿米巴id ReceiveAmibaId
                        if (amibaStaff.getAmibaId().equals(informationWorkOrder.getReceiveAmibaId())) {
                            this.assignee(nextWorkOrderNo,
                                    assignessStaff.getStaffCode(),
                                    informationWorkOrder.getReceiveAmibaId(),
                                    informationWorkOrder.getClaimStaffCode(),
                                    "自动分配",
                                    "System"
                            );
                        }


                    }
                }

                //收服务费工单: 财务->销售, 分配给商务经理
                if (nextWorkOrderTypeCode.equals(WorkOrderTypeCode.LOAN_FEE)) {
                    Order order = orderService.findByOrderNo(workOrder.getOrderNo());
                    List<AmibaStaff> salerAmibaStaffs = amibaStaffService.findByAmibaId(order.getBusinessManagerAmibaId());
                    AmibaStaff salerManager = salerAmibaStaffs.stream().filter(m -> m.getRole() == AmibaStaffRole.MANAGER.getValue()).findFirst().orElse(null);

                    this.assignee(nextWorkOrderNo,
                            salerManager.getStaffCode(),
                            order.getBusinessManagerAmibaId(),
                            order.getBusinessManagerStaffCode(),
                            "系统自动分配",
                            "System"
                    );
                }
            }
        }
    }

    /**
     * 取一个工单受理方有效发配人
     *
     * @param workOrder
     * @param receiveStaffs
     * @return
     */
    private AmibaStaff getAssignessStaff(WorkOrder workOrder, List<AmibaStaff> receiveStaffs) {
        AmibaStaff assigneeStaff;

        // 之前的分配人, 是否已被调整走了
        Optional<AmibaStaff> assigneeStaffOptional = receiveStaffs.stream()
                .filter(s -> s.getStaffCode().equals(workOrder.getAssigneeStaffCode()))
                .filter(s -> s.getRole() == AmibaStaffRole.MANAGER.getValue())
                .findFirst();
        if (assigneeStaffOptional.isPresent()) {
            assigneeStaff = assigneeStaffOptional.get();
        } else {
            assigneeStaffOptional = receiveStaffs.stream()
                    .filter(s -> s.getRole() == AmibaStaffRole.MANAGER.getValue())
                    .findFirst();
            if (!assigneeStaffOptional.isPresent()) {
                throw new CRMException("你所属的阿米巴没有设置巴长");
            }
            assigneeStaff = assigneeStaffOptional.get();
        }

        return assigneeStaff;
    }

    /**
     * 创建工单
     *
     * @param orderNo           订单号
     * @param createStaffCode   创建人
     * @param workOrderTypeCode 工单类型
     * @param remark            工单备注
     * @param createBy          创建人姓名
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult<String> create(String orderNo,
                                        String createStaffCode,
                                        WorkOrderTypeCode workOrderTypeCode,
                                        String remark,
                                        String createBy,
                                        Integer receiveAmibaId) {
        if (workOrderTypeCode.equals(WorkOrderTypeCode.INFORMATION)) {
            AssertUtils.notNull(receiveAmibaId, "请选择交付巴！");
        }
        //如果已经存在 就不创建了
        Boolean exist = this.workOrderExist(orderNo, workOrderTypeCode);
        if (exist) {
            logger.error("该工单已经存在，orderNo {},workOrderTypeCode {}", orderNo, workOrderTypeCode);
            throw new CRMException("该工单已存在, 不能重复创建.");
        }

        // 获取工单类型
        WorkOrderType workOrderType = workOrderTypeService.findByCode(workOrderTypeCode);

        if (workOrderType == null) {
            logger.error("工单类型不存在，workOrderTypeId {}", workOrderTypeCode);
            return new ServiceResult<>(false);
        }

        // 工单类型发起方阿米巴
        Amiba amibaCode = amibaService.findById(workOrderType.getAmibaSourceId());

        // 发起阿米巴
        Amiba sourceAmiba = new Amiba();
        BeanUtils.copyProperties(amibaCode, sourceAmiba);

        // 如果发起巴是商务巴, 则发起人应该是商务经理
        if (amibaCode.getCode().equals(AmibaCode.XIAO_SHOU)) {
            Order order = orderService.findByOrderNo(orderNo);
            createStaffCode = order.getBusinessManagerStaffCode();
            sourceAmiba = amibaService.findById(order.getBusinessManagerAmibaId());
        }
        // 如果发起巴是交付巴, 则发起人应该是交付经理
        if (amibaCode.getCode().equals(AmibaCode.JIAO_FU)) {
            Order order = orderService.findByOrderNo(orderNo);
            createStaffCode = order.getDeliverManagerStaffCode(); // 交付经理
            sourceAmiba = amibaService.findById(order.getDeliverManagerAmibaId()); // 交付经理所在阿米巴
        }
        // 如果发起巴是财务巴, 则发起人应该是财务巴巴长
        if (amibaCode.getCode().equals(AmibaCode.CAI_WU)) {
            List<AmibaStaff> managers = amibaStaffService.findManagerByAmibaCode(AmibaCode.CAI_WU);
            if (Objects.nonNull(managers) && managers.size() > 0) {
                //发起人
                createStaffCode = managers.get(0).getStaffCode();
                sourceAmiba = amibaService.findById(managers.get(0).getAmibaId());
            }
        }

        //查询工单的创建人
        AmibaStaff createStaff = amibaStaffService.findSingleByStaffCode(createStaffCode);

        //申请工单号
        String workOrderNo = sequenceService.generateWordOrderNo(workOrderType.getCode().getKey());

        WorkOrder workOrder = new WorkOrder();
        //订单
        workOrder.setOrderNo(orderNo);
        //工单
        workOrder.setWorkOrderTypeId(workOrderType.getId());
        workOrder.setWorkOrderTypeCode(workOrderTypeCode);
        workOrder.setWorkOrderNo(workOrderNo);
        workOrder.setCreatedBy(createBy);
        workOrder.setStatus(UN_ASSIGNEE);
        workOrder.setBack(BackStatus.NO);
        workOrder.setRemark(remark);
        //发起巴
        workOrder.setCreateAmibaId(sourceAmiba.getId());
        workOrder.setCreateAmibaName(sourceAmiba.getName());
        //发起人
        workOrder.setCreateStaffCode(createStaff.getStaffCode());
        workOrder.setCreateStaffName(createStaff.getStaffName());
        //受理巴
        if (workOrderType.getCode().equals(WorkOrderTypeCode.INFORMATION)) {
            workOrder.setReceiveAmibaId(receiveAmibaId);
            Amiba amiba = amibaService.findById(receiveAmibaId);
            workOrder.setReceiveAmibaName(amiba.getName());
        } else {
            workOrder.setReceiveAmibaId(workOrderType.getAmibaTargetId());
            workOrder.setReceiveAmibaName(workOrderType.getAmibaTargetName());
        }
        workOrderMapper.insertSelective(workOrder);

        // 如果是资料采集工单, 需要修改订单状态和发送消息给资产管理系统
        if (workOrderTypeCode.equals(WorkOrderTypeCode.INFORMATION)) {
            Order updateOrder = new Order();
            updateOrder.setOrderNo(orderNo);
            updateOrder.setStatus(OrderStatus.STATUS_COLLECT);
            updateOrder.setOperStaffCode(createStaffCode);
            updateOrder.setDeliverManagerAmibaId(receiveAmibaId);
            updateOrder.setCreatedBy(createBy);
            //修改订单的受理时间
            updateOrder.setSubmitTime(new Date());
            //修改产品信息
            Amiba amiba = amibaService.findById(receiveAmibaId);
            updateOrder.setProductId(amiba.getProductId());
            orderService.updateStatus(updateOrder);

            orderService.updateBank(orderNo);

            // 消息通知任务日志
            messageSendTaskService.save(MessageSendType.WORK_ORDER_TO_BE_ASSIGNEE_MSG,
                    workOrder.getWorkOrderNo(),
                    UUID.randomUUID().toString(),
                    TopicConsts.TO_BE_ASSIGNEED_NOTIFY_TOPIC,
                    workOrder);
            //创建采集工单成功后，则boss发送消息给资产管理系统
            OrderInfo2CapitalMessage orderInfo2CapitalMessage = new OrderInfo2CapitalMessage();
            orderInfo2CapitalMessage.setOrderNo(orderNo);
            Order order = orderService.findByOrderNo(orderNo);
            if (Objects.nonNull(order)) {
                //发起人员工编号
                orderInfo2CapitalMessage.setProcessorCode("BOSS系统自动创建");
                //发起人员工姓名
                orderInfo2CapitalMessage.setProcessorName("BOSS系统自动创建");

                if (Objects.isNull(order.getChannelName())||"".equals(order.getChannelName())){
                    orderInfo2CapitalMessage.setChannelName("未知渠道");
                }else {
                    orderInfo2CapitalMessage.setChannelName(order.getChannelName());
                }
                //客户姓名
                orderInfo2CapitalMessage.setCustomerName(order.getName());
                orderInfo2CapitalMessage.setBusinessCode(order.getBusinessManagerStaffCode());
                orderInfo2CapitalMessage.setBusinessName(order.getBusinessManager());
                orderInfo2CapitalMessage.setAmibaId(order.getDeliverManagerAmibaId());
                Amiba deliverAmiba = amibaService.findById(order.getDeliverManagerAmibaId());
                if (Objects.nonNull(deliverAmiba)) {
                    orderInfo2CapitalMessage.setAmibaName(amiba.getName());
                }
                // 设置交付经理
                orderInfo2CapitalMessage.setDeliverStaffCode(order.getDeliverManagerStaffCode());
                orderInfo2CapitalMessage.setDeliverStaffName(order.getDeliverManager());
            }
            //消息通知任务日志
            messageSendTaskService.save(MessageSendType.APPROVAL_WORK_ORDER_COMPLETED,
                    orderInfo2CapitalMessage.getOrderNo(),
                    orderInfo2CapitalMessage.getOrderNo()+TopicConsts.ORDER_INFO_TO_CAPITAL_NOTIFY_TOPIC,
                    TopicConsts.ORDER_INFO_TO_CAPITAL_NOTIFY_TOPIC,
                    orderInfo2CapitalMessage);
        }

        try {
            commonLogService.add(CommonLogType.WORK_ORDER,
                    CommonLogType.WORK_ORDER_GENERATE,
                    workOrder.getWorkOrderNo(),
                    "工单已提交",
                    workOrder.getCreatedBy());
        } catch (Exception e) {
            throw new CRMException("创建初始化日志失败", e);
        }
        return ServiceResult.of(workOrderNo);
    }

    /**
     * 删除协作人
     *
     * @param workOrder
     * @param currentStaffCode
     * @param currentStaffName
     */
    private void removeAssistUser(Order order, WorkOrder workOrder, String currentStaffCode, String currentStaffName) {
        String orderNo = workOrder.getOrderNo();
        //原来工单的执行的人(原来的协作人)
        String claimStaffCode = workOrder.getClaimStaffCode();
        //删除协作人
        orderAssistUserMapper.removeByOrderNoAndStaffCode(orderNo, claimStaffCode);
        // 新增订单协作人变更任务
        OrderTaskLog orderTaskLog = new OrderTaskLog();
        orderTaskLog.setModifiedBy(currentStaffName);
        orderTaskLog.setOrderNo(orderNo);
        orderTaskLog.setType(OrderTaskLogType.ORDER_ASSIST_USER_CHANGE);
        orderTaskLog.setStaffCode(currentStaffCode);
        List<OrderAssistUser> orderAssistUserList = orderAssistUserMapper.selectByOrderNo(orderNo);
        if (!orderAssistUserList.isEmpty()) {
            try {
                orderTaskLog.setContent(JsonUtil.toJson(orderAssistUserList));
            } catch (CRMException e) {

            }
        }
        //记录删除协作人记录
        AmibaStaff assistant = amibaStaffService.findSingleByStaffCode(claimStaffCode);
        if (Objects.isNull(assistant)) {
            return;
        }
        OrderMemorandum orderMemorandum = new OrderMemorandum();
        orderMemorandum.setContent("删除协作人 " + assistant.getStaffName());
        orderMemorandum.setOrderNo(orderNo);
        orderMemorandum.setStaffName(assistant.getStaffName());
        orderMemorandum.setModifiedBy(currentStaffName);
        orderMemorandum.setType(OrderMemorandumTypeEnum.LOG);
        //头像
        UserWechat userWechat = userWechatMapper.selectByStaffCode(currentStaffCode);
        if (Objects.nonNull(userWechat) && StringUtils.isNotEmpty(userWechat.getAvatar())) {
            orderMemorandum.setAvatarUrl(userWechat.getAvatar());
        }
        orderMemorandumService.save(orderMemorandum);

        //消息体
        OrderCollaboratorMessage message = new OrderCollaboratorMessage();
        message.setCollaborator(assistant.getStaffName());
        List<String> staffCodes = new ArrayList<>();
        staffCodes.add(assistant.getStaffCode());
        message.setCollaboratorStaffCode(staffCodes);
        message.setFlag(1);
        message.setOperator(currentStaffName);
        message.setName(order.getName());
        message.setOrderNo(orderNo);
        messageSendTaskService.save(MessageSendType.ORDER_COLLABORATOR_LOG_CHANGE_MSG, orderNo, UUID.randomUUID().toString(), TopicConsts.WORK_ORDER_ORDER_ASSIST_USER_CHANGE, message);
    }

    /**
     * 添加协作人
     */
    private void saveOrderAssistUser(Order order, AmibaStaff assistant) {
        //先根据订单号去查询
        List<OrderAssistUser> orderAssistUserList = orderAssistUserMapper.selectByOrderNo(order.getOrderNo());
        List<String> collect = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(orderAssistUserList)) {
            collect = orderAssistUserList.stream().map(OrderAssistUser::getStaffCode).collect(Collectors.toList());
            if (collect.contains(assistant.getStaffCode())) {
                return;
            }
        }
        OrderAssistUser orderAssistUser = new OrderAssistUser();
        orderAssistUser.setCreatedBy(order.getCurrentStaffName());
        orderAssistUser.setModifiedBy(order.getCurrentStaffName());
        orderAssistUser.setOrderNo(order.getOrderNo());
        orderAssistUser.setStaffCode(assistant.getStaffCode());
        orderAssistUser.setAmibaName(assistant.getAmibaName());
        orderAssistUser.setStaffName(assistant.getStaffName());
        orderAssistUser.setAmibaId(assistant.getAmibaId());
        orderAssistUserMapper.insert(orderAssistUser);
        // 新增订单协作人变更任务
        OrderTaskLog orderTaskLog = new OrderTaskLog();
        orderTaskLog.setModifiedBy(order.getCurrentStaffName());
        orderTaskLog.setOrderNo(order.getOrderNo());
        orderTaskLog.setType(OrderTaskLogType.ORDER_ASSIST_USER_CHANGE);
        orderTaskLog.setStaffCode(order.getCurrentStaffCode());
        try {
            orderTaskLog.setContent(JsonUtil.toJson(orderAssistUser));
        } catch (CRMException e) {

        }
        orderTaskLogMapper.insertSelective(orderTaskLog);
        OrderMemorandum orderMemorandum = new OrderMemorandum();
        orderMemorandum.setContent("新增协作人 " + assistant.getStaffName());
        orderMemorandum.setOrderNo(order.getOrderNo());
        orderMemorandum.setStaffName(order.getCurrentStaffName());
        orderMemorandum.setModifiedBy(order.getCurrentStaffName());
        orderMemorandum.setType(OrderMemorandumTypeEnum.LOG);
        //头像
        UserWechat userWechat = userWechatMapper.selectByStaffCode(order.getCurrentStaffCode());
        if (Objects.nonNull(userWechat) && StringUtils.isNotEmpty(userWechat.getAvatar())) {
            orderMemorandum.setAvatarUrl(userWechat.getAvatar());
        }
        orderMemorandumService.save(orderMemorandum);

        //消息体
        OrderCollaboratorMessage message = new OrderCollaboratorMessage();
        message.setCollaborator(assistant.getStaffName());
        List<String> staffCodes = new ArrayList<>();
        staffCodes.add(assistant.getStaffCode());
        message.setCollaboratorStaffCode(staffCodes);
        message.setFlag(0);
        message.setOperator(order.getCurrentStaffName());
        message.setName(order.getName());
        message.setOrderNo(order.getOrderNo());
        messageSendTaskService.save(MessageSendType.ORDER_COLLABORATOR_LOG_CHANGE_MSG, order.getOrderNo(), UUID.randomUUID().toString(), TopicConsts.WORK_ORDER_ORDER_ASSIST_USER_CHANGE, message);
    }

}